home *** CD-ROM | disk | FTP | other *** search
- /*
-
- Copyright (C) 1995,96,97,98
- Free Software Foundation, Inc.
-
- This file is part of GNU cfengine - written and maintained
- by Mark Burgess, Dept of Computing and Engineering, Oslo College,
- Dept. of Theoretical physics, University of Oslo
-
- This program is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the
- Free Software Foundation; either version 2, or (at your option) any
- later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
-
- */
-
- /*******************************************************************/
- /* */
- /* Cfengine : remote server daemon example */
- /* */
- /*******************************************************************/
-
- #define INET 1
-
-
- #include "cf.defs.h"
- #include "cf.extern.h"
- #include "../pub/getopt.h"
- #include "cfd.h"
-
- #ifdef HAVE_TCPD_H
- # include <tcpd.h>
- #endif
-
- #ifdef HAVE_PTHREAD_H
- # include <pthread.h>
- #endif
-
- #ifdef HAVE_SCHED_H
- # include <sched.h>
- #endif
-
- #ifdef HAVE_PTHREAD_H
- pthread_attr_t PTHREADDEFAULTS;
- pthread_mutex_t MUTEX_COUNT = PTHREAD_MUTEX_INITIALIZER;
- pthread_mutex_t MUTEX_HOSTNAME = PTHREAD_MUTEX_INITIALIZER;
- #endif
-
- /*******************************************************************/
- /* Level 0 : Main */
- /*******************************************************************/
-
- main (argc,argv)
-
- int argc;
- char **argv;
-
- {
- CheckOptsAndInit(argc,argv);
- GetNameInfo();
- ParseInputFiles();
-
- if (PARSEONLY)
- {
- exit(0);
- }
-
- CheckVariables();
- SummarizeParsing();
- StartServer(argc,argv);
-
- /* Never exit here */
- }
-
- /********************************************************************/
- /* Level 1 */
- /********************************************************************/
-
- CheckOptsAndInit(argc,argv)
-
- int argc;
- char **argv;
-
- { extern char *optarg;
- int optindex = 0;
- int c, i;
-
- umask(0);
- openlog(VPREFIX,LOG_PID|LOG_NOWAIT|LOG_ODELAY,LOG_DAEMON);
- strcpy(VINPUTFILE,CFD_INPUT);
- OUTPUT[0] = '\0';
- VFQNAME[0] = '\0';
-
- ISCFENGINE = false; /* Switch for the parser */
- PARSEONLY = false;
-
- InitHashTable();
-
- AddClassToHeap("any"); /* This is a reserved word / wildcard */
-
- while ((c=getopt_long(argc,argv,"d:f:vmhpFV",CFDOPTIONS,&optindex)) != EOF)
- {
- switch ((char) c)
- {
- case 'f': strncpy(VINPUTFILE,optarg,bufsize-1);
- break;
-
- case 'd':
-
- switch (*optarg)
- {
- case '1': D1 = true;
- break;
- case '2': D2 = true;
- break;
- default: DEBUG = true;
- break;
- }
-
- NO_FORK = true;
- printf("cfd: Debug mode: running in foreground\n");
- break;
-
- case 'v': VERBOSE = true;
- break;
-
- case 'V': printf("GNU %s daemon\n%s\n",CFVERSION,COPYRIGHT);
- printf("This program is covered by the GNU Public License and may be\n");
- printf("copied free of charge. No warrenty is implied.\n\n");
- exit(0);
- break;
-
- case 'p': PARSEONLY = true;
- break;
-
- case 'F': NO_FORK = true;
- break;
-
- case 'm': /* No longer needed */
- break;
-
- default: Syntax();
- exit(1);
-
- }
- }
-
-
- LOGGING = true; /* Do output to syslog */
-
- sprintf(VPREFIX,"cfd:%s:",VUQNAME);
- sprintf(VBUFF,"%s/test",LOCKFILEDIR);
- MakeDirectoriesFor(VBUFF);
- strncpy(VLOCKDIR,LOCKFILEDIR,bufsize-1);
-
- sprintf(VBUFF,"%s/test",LOGFILEDIR);
-
- MakeDirectoriesFor(VBUFF);
- strncpy(VLOGDIR,LOGFILEDIR,bufsize-1);
-
- strcpy(VDOMAIN,"undefined.domain");
-
- strncpy(VCANONICALFILE,CanonifyName(VINPUTFILE),bufsize-1);
- }
-
- /*******************************************************************/
-
- CheckVariables()
-
- { struct stat statbuf;
- int i, value = -1;
-
- #ifdef HAVE_LIBPTHREAD
- CfLog(cfinform,"Multithreaded version","");
- #else
- CfLog(cfinform,"Single threaded version","");
- #endif
-
- strncpy(VFQNAME,VSYSNAME.nodename,bufsize-1);
- LoadSecretKeys();
-
- if ((CFDSTARTTIME = time((time_t *)NULL)) == -1)
- {
- printf("Couldn't read system clock\n");
- }
-
- if (GetMacroValue("CheckIdent") && (strcmp(GetMacroValue("CheckIdent"),"on") == 0))
- {
- CHECK_RFC931 = true;
- }
-
- if (GetMacroValue("DenyBadClocks") && (strcmp(GetMacroValue("DenyBadClocks"),"off") == 0))
- {
- DENYBADCLOCKS = false;
- }
-
-
- bzero(CHECKSUMDB,bufsize);
-
- if (GetMacroValue("ChecksumDatabase"))
- {
- ExpandVarstring("$(ChecksumDatabase)",CHECKSUMDB,NULL);
-
- if (*CHECKSUMDB != '/')
- {
- FatalError("$(ChecksumDatabase) does not expand to an absolute filename\n");
- }
- }
-
-
-
- if (GetMacroValue("IfElapsed"))
- {
- ExpandVarstring("$(IfElapsed)",VBUFF,NULL);
- sscanf(VBUFF,"%d",&value);
-
- if (value < 0)
- {
- printf("cfd: silly IfElapsed value in control\n");
- exit(1);
- }
- else
- {
- VIFELAPSED = value;
- Verbose("cfd: IfElapsed time: %d minutes\n",VIFELAPSED);
- }
- }
-
- bzero(VBUFF,bufsize);
-
- if (GetMacroValue("cfrunCommand"))
- {
- ExpandVarstring("$(cfrunCommand)",VBUFF,NULL);
-
- if (*VBUFF != '/')
- {
- FatalError("$(cfrunCommand) does not expand to an absolute filename\n");
- }
-
- sscanf(VBUFF,"%4095s",CFRUNCOMMAND);
- Debug("cfrunCommand is %s\n",CFRUNCOMMAND);
-
- if (stat(CFRUNCOMMAND,&statbuf) == -1)
- {
- FatalError("$(cfrunCommand) points to a non-existent file\n");
- }
- }
-
- if (GetMacroValue("MaxConnections"))
- {
- bzero(VBUFF,bufsize);
- ExpandVarstring("$(MaxConnections)",VBUFF,NULL);
- Debug("$(MaxConnections) Expanded to %s\n",VBUFF);
-
- CFD_MAXPROCESSES = atoi(VBUFF);
-
- if ((CFD_MAXPROCESSES < 1) || (CFD_MAXPROCESSES > 100))
- {
- FatalError("cfd: MaxConnections with silly value");
- }
- }
- else
- {
- CFD_MAXPROCESSES = 10;
- }
-
- if (GetMacroValue("AutoExecInterval"))
- {
- bzero(VBUFF,bufsize);
- ExpandVarstring("$(AutoExecInterval)",VBUFF,NULL);
- Debug("$(AutoExecInterval) Expanded to %s\n",VBUFF);
-
- CFD_INTERVAL = 60 * atoi(VBUFF);
-
- if ((CFD_INTERVAL < 0) || (CFD_INTERVAL > 60*24*7))
- {
- FatalError("cfd: AutoExecInterval with silly value in minutes (>0 and less than 1 week)");
- }
- }
- else
- {
- CFD_INTERVAL = 0;
- }
-
- Debug("MaxConnections = %d\n",CFD_MAXPROCESSES);
- Debug("AutoExecInterval = %d\n",CFD_INTERVAL);
-
- CHECKSUMUPDATES = true;
-
- if (GetMacroValue("ChecksumUpdates") && (strcmp(GetMacroValue("ChecksumUpdates"),"off") == 0))
- {
- CHECKSUMUPDATES = false;
- }
-
- i = 0;
-
- if (strstr(VSYSNAME.nodename,ToLowerStr(VDOMAIN)))
- {
- strncpy(VFQNAME,VSYSNAME.nodename,bufsize-1);
-
- while(VSYSNAME.nodename[i++] != '.')
- {
- }
-
- strncpy(VUQNAME,VSYSNAME.nodename,i-1);
- }
- else
- {
- sprintf(VFQNAME,"%s.%s",VSYSNAME.nodename,ToLowerStr(VDOMAIN));
- strncpy(VUQNAME,VSYSNAME.nodename,bufsize-1);
- }
- }
-
- /*******************************************************************/
-
- SummarizeParsing()
-
- { struct Auth *ptr;
- struct Item *ip,*ipr;
-
- if (DEBUG || D2 || D3)
- {
- printf("ACCESS GRANTED ----------------------:\n\n");
-
- for (ptr = VADMIT; ptr != NULL; ptr=ptr->next)
- {
- printf("Path: %s (secure=%d)\n",ptr->path,ptr->secure);
-
- for (ip = ptr->accesslist; ip != NULL; ip=ip->next)
- {
- printf(" Admit: %s root=",ip->name);
- for (ipr = ptr->maproot; ipr !=NULL; ipr=ipr->next)
- {
- printf("%s,",ipr->name);
- }
- printf("\n");
- }
- }
-
- printf("ACCESS DENIAL ------------------------ :\n\n");
-
- for (ptr = VDENY; ptr != NULL; ptr=ptr->next)
- {
- printf("Path: %s\n",ptr->path);
-
- for (ip = ptr->accesslist; ip != NULL; ip=ip->next)
- {
- printf(" Deny: %s\n",ip->name);
- }
- }
-
- printf("Hosts denied access to :\n\n");
- }
-
-
- if (ERRORCOUNT > 0)
- {
- FatalError("Execution terminated after parsing due to errors in program");
- }
- }
-
- /*******************************************************************/
-
- StartServer(argc,argv)
-
- int argc;
- char **argv;
-
- { struct sockaddr_in cin, sin;
- char recvbuffer[bufsize], sendbuffer[bufsize];
- struct servent *server;
- int sd, sd_reply, addrlen = sizeof(cin),ageing;
- struct cfd_connection *conn;
- int portnumber, yes=1, shmid;
- struct linger cflinger;
- void ExitCleanly(), AutoExec();
-
- /* Initialize cflinger */
-
- cflinger.l_onoff = 1;
- cflinger.l_linger = 60;
-
- if ((!NO_FORK) && (fork() != 0))
- {
- sprintf(OUTPUT,"cfd: starting %.24s\n",ctime(&CFDSTARTTIME));
- CfLog(cfinform,OUTPUT,"");
- exit(0);
- }
-
- if (!NO_FORK)
- {
- #ifdef HAVE_SETSID
- setsid();
- #endif
- fclose (stdin);
- fclose (stdout);
- fclose (stderr);
- closelog();
- }
-
- signal(SIGINT,ExitCleanly);
- signal(SIGTERM,ExitCleanly);
- signal(SIGHUP,SIG_IGN);
- signal(SIGPIPE,SIG_IGN);
- signal(SIGALRM,(void *)AutoExec);
-
- sprintf(OUTPUT,"Setting alarm to %d seconds\n",CFD_INTERVAL);
- CfLog(cfinform,OUTPUT,"");
- alarm(CFD_INTERVAL);
-
- if ((server = getservbyname(CFENGINE_SERVICE,"tcp")) == NULL)
- {
- CfLog(cferror,"Couldn't get cfengine service","getservbyname");
- exit (1);
- }
-
- bzero(&cin,sizeof(cin));
-
- sin.sin_port = (unsigned short)(server->s_port); /* Service returns network byte order */
- sin.sin_addr.s_addr = INADDR_ANY;
- sin.sin_family = AF_INET;
-
- if ((sd = socket(AF_INET,SOCK_STREAM,0)) == -1)
- {
- CfLog(cferror,"Couldn't open socket","socket");
- exit (1);
- }
-
- if (setsockopt (sd, SOL_SOCKET, SO_REUSEADDR, (char *) &yes, sizeof (int)) == -1)
- {
- CfLog(cferror,"Couldn't set socket options","sockopt");
- exit (1);
- }
-
- if (setsockopt (sd, SOL_SOCKET, SO_LINGER, (char *) &cflinger, sizeof (struct linger)) == -1)
- {
- CfLog(cferror,"Couldn't set socket options","sockopt");
- exit (1);
- }
-
- if (bind(sd,(struct sockaddr *)&sin,sizeof(sin)) == -1) /* Must have this on server */
- {
- CfLog(cferror,"Couldn't bind to socket","bind");
- exit(1);
- }
-
- if (listen(sd,queuesize) == -1)
- {
- CfLog(cferror,"listen failed","listen");
- exit(1);
- }
-
- Verbose("Listening for connections on port %d..\n",ntohs(server->s_port));
-
- ageing = 0;
-
- while (true)
- {
- if ((sd_reply = accept(sd, (struct sockaddr *)&cin, &addrlen)) == -1)
- {
- continue;
- }
- else
- {
- if (ageing++ > CFD_MAXPROCESSES*4) /* Insurance against stale db */
- { /* estimate number of clients */
- unlink(CHECKSUMDB); /* arbitrary policy .. */
- ageing = 0;
- }
- SpawnConnection(sd_reply);
- CheckFileChanges(argc,argv,sd);
- }
- }
- }
-
- /*********************************************************************/
- /* Level 2 */
- /*********************************************************************/
-
- Syntax()
-
- { int i;
-
- printf("GNU cfengine daemon: server module\n%s\n%s\n",CFVERSION,COPYRIGHT);
- printf("\n");
- printf("Options:\n\n");
-
- for (i=0; CFDOPTIONS[i].name != NULL; i++)
- {
- printf("--%-20s (-%c)\n",CFDOPTIONS[i].name,(char)CFDOPTIONS[i].val);
- }
-
- printf("\nBug reports to bug-cfengine@prep.ai.mit.edu (News: gnu.cfengine.bug)\n");
- printf("General help to help-cfengine@prep.ai.mit.edu (News: gnu.cfengine.help)\n");
- printf("Info & fixes at http://www.iu.hioslo.no/~mark/cfengine.html\n");
- }
-
- /*********************************************************************/
-
- SpawnConnection(sd_reply)
-
- int sd_reply;
-
- { struct cfd_connection *conn;
- struct cfd_connection *NewConn();
-
- #ifdef HAVE_PTHREAD_H
- pthread_t tid;
- size_t size = 0;
- #endif
- void *HandleConnection();
-
- Debug("New connection...\n");
- conn = NewConn(sd_reply);
-
- #ifdef HAVE_LIBPTHREAD
-
- Debug("Spawning new thread...\n");
-
- pthread_attr_init(&PTHREADDEFAULTS);
- pthread_attr_setdetachstate(&PTHREADDEFAULTS,PTHREAD_CREATE_DETACHED);
-
- #ifdef HAVE_PTHREAD_ATTR_SETSTACKSIZE
- pthread_attr_setstacksize(&PTHREADDEFAULTS,(size_t)(sysconf(_SC_THREAD_STACK_MIN)+100*1024));
- #endif
-
- if (pthread_create(&tid,&PTHREADDEFAULTS,HandleConnection,(void *)conn) != 0)
- {
- CfLog(cferror,"pthread_create failed","create");
- HandleConnection(conn);
- }
-
- pthread_attr_destroy(&PTHREADDEFAULTS);
-
- #else
-
- /* Can't fork here without getting a zombie on some systems ? */
-
- Debug("Single threaded...\n");
-
- HandleConnection(conn);
-
- #endif
- }
-
- /**************************************************************/
-
- CheckFileChanges(argc,argv,sd)
-
- int argc;
- char **argv;
- int sd;
-
- { struct stat newstat;
- char filename[bufsize],line[bufsize], *sp;
- char arg[maxshellargs][bufsize];
- FILE *pp;
- int i;
-
- bzero(&newstat,sizeof(struct stat));
- bzero(filename,bufsize);
-
- if ((sp=getenv(CFINPUTSVAR)) != NULL)
- {
- if (! IsAbsoluteFileName(VINPUTFILE)) /* Don't prepend to absolute names */
- {
- strncpy(filename,sp,bufsize-1);
- AddSlash(filename);
- }
- }
-
- strcat(filename,VINPUTFILE);
-
- if (stat(filename,&newstat) == -1)
- {
- sprintf(OUTPUT,"Input file %s missing!\n",filename);
- CfLog(cferror,OUTPUT,filename);
- return;
- }
-
- Debug("Checking file updates on %s (%x/%x)\n",filename, newstat.st_ctime, CFDSTARTTIME);
-
- if (CFDSTARTTIME < newstat.st_ctime)
- {
- sprintf(OUTPUT,"Rereading config files %s..\n",filename);
- CfLog(cfinform,OUTPUT,"");
-
- /* Free up memory */
-
- for (i = 0; i < hashtablesize; i++)
- {
- if (HASH[i] != NULL)
- {
- free(HASH[i]);
- HASH[i] = NULL;
- }
- }
-
- DeleteItemList(VHEAP);
- DeleteItemList(VNEGHEAP);
- DeleteAuthList(VADMIT);
- strcpy(VDOMAIN,"undefined.domain");
-
- VADMIT = VADMITTOP = NULL;
- VHEAP = VNEGHEAP = NULL;
-
- AddClassToHeap("any");
- GetNameInfo();
- ParseInputFiles();
- CheckVariables();
- LoadSecretKeys();
- alarm(CFD_INTERVAL);
- }
- }
-
- /*********************************************************************/
- /* Level 3 */
- /*********************************************************************/
-
- void *HandleConnection(conn)
-
- struct cfd_connection *conn;
-
- {
- #if defined HAVE_PTHREAD_H && defined HAVE_LIBPTHREAD
- #ifdef HAVE_PTHREAD_SIGMASK
- sigset_t sigmask;
-
- sigemptyset(&sigmask);
- pthread_sigmask(SIG_BLOCK,&sigmask,NULL);
- #endif
-
- if (pthread_mutex_lock(&MUTEX_COUNT) != 0)
- {
- CfLog(cferror,"pthread_mutex_lock failed","pthread_mutex_lock");
- DeleteConn(conn);
- return NULL;
- }
-
- ACTIVE_THREADS++;
-
- if (pthread_mutex_unlock(&MUTEX_COUNT) != 0)
- {
- CfLog(cferror,"pthread_mutex_unlock failed","unlock");
- }
-
- if (ACTIVE_THREADS >= CFD_MAXPROCESSES)
- {
- CfLog(cfinform,"Too many threads","");
- DeleteConn(conn);
- return;
- }
-
- #endif
-
- while (BusyWithConnection(conn))
- {
- }
-
- DeleteConn(conn);
-
- #ifdef HAVE_LIBPTHREAD
-
- Debug("Terminating thread...\n");
-
- if (pthread_mutex_lock(&MUTEX_COUNT) != 0)
- {
- CfLog(cferror,"pthread_mutex_lock failed","pthread_mutex_lock");
- return;
- }
-
- ACTIVE_THREADS--;
-
- if (pthread_mutex_unlock(&MUTEX_COUNT) != 0)
- {
- CfLog(cferror,"pthread_mutex_unlock failed","unlock");
- }
-
- #endif
-
- }
-
- /*********************************************************************/
-
- BusyWithConnection(conn)
-
- struct cfd_connection *conn;
-
- /* This is the protocol section. Here we must */
- /* check that the incoming data are sensible */
- /* and extract the information from the message */
-
- { time_t tloc, trem = 0;
- char recvbuffer[bufsize], sendbuffer[bufsize],check[bufsize];
- char filename[bufsize],buffer[bufsize],args[bufsize],out[bufsize];
- long time_no_see = 0;
- int len=0, drift;
- struct cfd_get_arg get_args;
-
- bzero(recvbuffer,bufsize);
- bzero(&get_args,sizeof(get_args));
-
- if (RecvSocketStream(conn->sd_reply,recvbuffer,bufsize,NULL) == -1)
- {
- return false;
- }
-
- recvbuffer[bufsize-1] = '\0';
-
- if (strlen(recvbuffer) == 0)
- {
- Debug("cfd: terminating NULL transmission!\n");
- return false;
- }
-
- Debug("Received: [%s] on socket %d\n",recvbuffer,conn->sd_reply);
-
- switch (GetCommand(recvbuffer))
- {
- case cfd_exec: bzero(args,bufsize);
- sscanf(recvbuffer,"EXEC %[^\n]",args);
-
- if (! conn->id_verified)
- {
- RefuseAccess(conn,sendbuffer);
- return false;
- }
-
- if (!AccessControl(CFRUNCOMMAND,conn,false))
- {
- RefuseAccess(conn,sendbuffer);
- return false;
- }
-
- if (!MatchClasses(conn))
- {
- Terminate(conn->sd_reply);
- return false;
- }
-
- alarm(CFD_INTERVAL); /* reset alarm */
-
- DoExec(conn,sendbuffer,args);
- Terminate(conn->sd_reply);
- return false;
-
- case cfd_auth: sprintf (sendbuffer,"BAD: Old protocol, you need to upgrade to 1.5.x\n");
- SendTransaction(conn,sendbuffer);
- return false;
-
- case cfd_cauth: conn->id_verified = VerifyConnection(conn,(char *)(recvbuffer+strlen("CAUTH ")));
- if (! conn->id_verified)
- {
- RefuseAccess(conn,sendbuffer);
- }
- return conn->id_verified; /* are we finished yet ? */
-
- case cfd_get: bzero(filename,bufsize);
- sscanf(recvbuffer,"GET %d %[^\n]",&(get_args.buf_size),filename);
-
- if (get_args.buf_size < 0 || get_args.buf_size > bufsize)
- {
- RefuseAccess(conn,sendbuffer);
- return false;
- }
-
- if (! conn->id_verified)
- {
- RefuseAccess(conn,sendbuffer);
- return false;
- }
-
- if (!AccessControl(filename,conn,false))
- {
- RefuseAccess(conn,sendbuffer);
- return false;
- }
-
- bzero(sendbuffer,bufsize);
-
- get_args.connect = conn;
- get_args.secure = false;
- get_args.replybuff = sendbuffer;
- get_args.replyfile = filename;
-
- CfGetFile(&get_args);
-
- return true;
-
- case cfd_sget: bzero(buffer,bufsize);
- sscanf(recvbuffer,"SGET %d %d",&len,&(get_args.buf_size));
- bcopy(recvbuffer+31,out,bufsize-32);
- cfdecrypt(out,buffer,CFDES1,CFDES2,CFDES3,len);
-
- sscanf(buffer,"%3s %8s %[^\n]",check,get_args.key,filename);
- Debug("Buffer was %s\n",buffer);
-
- if (strcmp(check,"GET") != 0)
- {
- RefuseAccess(conn,sendbuffer);
- return false;
- }
-
- if (get_args.buf_size < 0 || get_args.buf_size > 8192)
- {
- RefuseAccess(conn,sendbuffer);
- return false;
- }
-
- Debug("Confirm decryption, and thus validity of caller\n");
- Debug("SGET %s with blocksize %d\n",filename,get_args.buf_size);
-
- if (! conn->id_verified)
- {
- RefuseAccess(conn,sendbuffer);
- return false;
- }
-
- if (!AccessControl(filename,conn,true))
- {
- RefuseAccess(conn,sendbuffer);
- return false;
- }
-
- bzero(sendbuffer,bufsize);
-
- get_args.connect = conn;
- get_args.secure = true;
- get_args.replybuff = sendbuffer;
- get_args.replyfile = filename;
-
- CfGetFile(&get_args);
- return true;
-
- case cfd_opendir: bzero(filename,bufsize);
- sscanf(recvbuffer,"OPENDIR %[^\n]",filename);
-
- if (! conn->id_verified)
- {
- RefuseAccess(conn,sendbuffer);
- return false;
- }
-
- if (!AccessControl(filename,conn,false))
- {
- RefuseAccess(conn,sendbuffer);
- return false;
- }
-
- CfOpenDirectory(conn,sendbuffer,filename);
- return true;
-
-
- case cfd_ssynch: bzero(buffer,bufsize);
- sscanf(recvbuffer,"SSYNCH %d",&len);
- bcopy(recvbuffer+23,out,bufsize-24);
- cfdecrypt(out,recvbuffer,CFDES1,CFDES2,CFDES3,len);
- if (strncmp(recvbuffer,"SYNCH",5) !=0)
- {
- RefuseAccess(conn,sendbuffer);
- return false;
- }
- /* roll through, no break */
-
- case cfd_synch:
- if (! conn->id_verified)
- {
- RefuseAccess(conn,sendbuffer);
- return false;
- }
-
- bzero(filename,bufsize);
- sscanf(recvbuffer,"SYNCH %ld STAT %[^\n]",&time_no_see,filename);
-
- trem = (time_t) time_no_see;
-
- if (time_no_see == 0 || filename[0] == '\0')
- {
- break;
- }
-
- if ((tloc = time((time_t *)NULL)) == -1)
- {
- sprintf(conn->output,"Couldn't read system clock\n");
- CfLog(cfinform,conn->output,"time");
- SendTransaction(conn,"BAD: clocks out of synch");
- return true;
- }
-
- drift = (int)(tloc-trem);
-
- if (DENYBADCLOCKS && (drift*drift > CLOCK_DRIFT*CLOCK_DRIFT))
- {
- sprintf(conn->output,"BAD: Clocks are too far unsynchronized %ld/%ld\n",(long)tloc,(long)trem);
- CfLog(cfinform,conn->output,"");
- SendTransaction(conn,conn->output);
- return true;
- }
- else
- {
- sprintf(conn->output,"Clocks were off by %ld\n",(long)tloc-(long)trem);
- CfLog(cfverbose,conn->output,"");
- StatFile(conn,sendbuffer,filename);
- }
-
- return true;
-
- case cfd_smd5: bzero(buffer,bufsize);
- sscanf(recvbuffer,"SMD5 %d",&len);
- bcopy(recvbuffer+23,out,bufsize-24);
- cfdecrypt(out,recvbuffer,CFDES1,CFDES2,CFDES3,len);
-
- if (strncmp(recvbuffer,"MD5",3) !=0)
- {
- RefuseAccess(conn,sendbuffer);
- return false;
- }
- /* roll through, no break */
-
- case cfd_md5:
- if (! conn->id_verified)
- {
- RefuseAccess(conn,sendbuffer);
- return false;
- }
-
- bzero(filename,bufsize);
- bzero(args,bufsize);
-
- CompareLocalChecksum(conn,sendbuffer,recvbuffer);
- return true;
- }
-
- sprintf (sendbuffer,"BAD: Malformed protocol request\n");
- SendTransaction(conn,sendbuffer);
- CfLog(cfinform,"Closing connection\n","");
- return false;
- }
-
- /**************************************************************/
-
- void ExitCleanly()
-
- { int i;
-
- sprintf(OUTPUT,"Exit -- (waiting for threads), pid = %d\n",getpid());
- CfLog(cfinform,OUTPUT,"");
- closelog();
-
- #ifdef HAVE_PTHREAD_H
- /* Do we care about this?
- for (i = 0; i < MAXTHREAD ; i++)
- {
- if (THREADS[i] != NULL)
- {
- pthread_join(THREADS[i],(void **)NULL);
- }
- }
- */
- #endif
-
- exit(0);
- }
-
- /**************************************************************/
-
- void AutoExec()
-
- { char logbuffer[bufsize], line[bufsize], *sp;
- FILE *pp;
- int print;
-
- alarm(0);
- VBUFF[0] = '\0';
-
- ExpandVarstring("$(AutoExecCommand)",VBUFF,"");
-
- if (strlen(VBUFF) == 0)
- {
- CfLog(cferror,"No $(AutoExecCommand) variable defined","");
- signal(SIGALRM,(void *)AutoExec);
- return;
- }
-
- /* Use same lock as for cfrun */
-
- if (!GetLock("cfd","exec",VIFELAPSED,VEXPIREAFTER,VUQNAME,CFSTARTTIME))
- {
- sprintf(OUTPUT,"cfd: Couldn't get a lock -- too soon: IfElapsed %d, ExpireAfter %d\n",VIFELAPSED,VEXPIREAFTER);
- CfLog(cferror,OUTPUT,"");
-
- return;
- }
-
- if (fork() == 0)
- {
- signal(SIGPIPE,SIG_IGN);
-
- ExpandVarstring("$(AutoExecCommand) --no-splay --inform",VBUFF,"");
-
- sprintf(OUTPUT,"Interval expired, executing command %s\n",VBUFF);
- CfLog(cfinform,OUTPUT,"");
-
- bzero(logbuffer,bufsize);
-
- if ((pp = cfpopen(VBUFF,"r")) == NULL)
- {
- sprintf(OUTPUT,"Couldn't open pipe to command %s\n",VBUFF);
- CfLog(cferror,OUTPUT,"cfpopen");
-
- return;
- }
-
- while (!feof(pp))
- {
- if (ferror(pp)) /* abortable */
- {
- fflush(pp);
- break;
- }
-
- ReadLine(line,1,pp);
-
- if (ferror(pp)) /* abortable */
- {
- fflush(pp);
- break;
- }
-
- print = false;
-
- for (sp = line; *sp != '\0'; sp++)
- {
- if (! isspace(*sp))
- {
- print = true;
- break;
- }
- }
-
- if (print)
- {
- sprintf(logbuffer,"%s\n",line);
- CfLog(cfinform,logbuffer,"");
- }
- }
-
- cfpclose(pp);
- closelog();
- return;
- }
-
- signal(SIGALRM,(void *)AutoExec);
- alarm(CFD_INTERVAL);
- }
-
- /**************************************************************/
- /* Level 4 */
- /**************************************************************/
-
- MatchClasses(conn)
-
- struct cfd_connection *conn;
-
- { char *sp, recvbuffer[bufsize];
- struct Item *classlist, *ip;
- int count = 0, n_read;
-
- Debug("Match classes\n");
-
- while (true)
- {
- count++;
-
- if (RecvSocketStream(conn->sd_reply,recvbuffer,bufsize,0) == -1)
- {
- if (errno == EINTR)
- {
- continue;
- }
- }
-
- Debug("Got class buffer %s\n",recvbuffer);
-
- if (strncmp(recvbuffer,CFD_TERMINATOR,strlen(CFD_TERMINATOR)) == 0)
- {
- if (count == 1)
- {
- Debug("No classes were sent, assuming no restrictions...\n");
- return true;
- }
-
- break;
- }
-
- classlist = SplitStringAsItemList(recvbuffer,' ');
-
- for (ip = classlist; ip != NULL; ip=ip->next)
- {
- if (IsDefinedClass(ip->name))
- {
- Debug("Class %s matched, accepting...\n",ip->name);
- DeleteItemList(classlist);
- return true;
- }
-
- if (strcmp(ip->name,CFD_TERMINATOR) == 0)
- {
- Debug("No classes matched, rejecting....\n");
- ReplyNothing(conn);
- DeleteItemList(classlist);
- return false;
- }
- }
- }
-
- ReplyNothing(conn);
- Debug("No classes matched, rejecting....\n");
- DeleteItemList(classlist);
- return false;
- }
-
- /**************************************************************/
-
- DoExec(conn,sendbuffer,args)
-
- struct cfd_connection *conn;
- char *sendbuffer;
- char *args;
-
- { char buffer[bufsize], line[bufsize], *sp;
- FILE *pp;
- int print,i;
-
- bzero(buffer,bufsize);
-
- if ((CFSTARTTIME = time((time_t *)NULL)) == -1)
- {
- CfLog(cferror,"Couldn't read system clock\n","time");
- }
-
- if (GetMacroValue("cfrunCommand") == NULL)
- {
- Verbose("cfd: exec request: no cfrunCommand defined\n");
- sprintf(sendbuffer,"Exec request: no cfrunCommand defined\n");
- SendTransaction(conn,sendbuffer);
- return;
- }
-
- for (sp = args; *sp != '\0'; sp++) /* Blank out -K -f */
- {
- if ((strncmp(sp,"-K",2) == 0) || (strncmp(sp,"-f",2) == 0))
- {
- *sp = ' ';
- *(sp+1) = ' ';
- }
- else if (strncmp(sp,"--no-lock",9) == 0)
- {
- for (i = 0; i < 9; i++)
- {
- *(sp+i) = ' ';
- }
- }
- else if (strncmp(sp,"--file",7) == 0)
- {
- for (i = 0; i < 7; i++)
- {
- *(sp+i) = ' ';
- }
- }
- }
-
- if (!GetLock("cfd","exec",VIFELAPSED,VEXPIREAFTER,VUQNAME,CFSTARTTIME))
- {
- sprintf(sendbuffer,"cfd: Couldn't get a lock -- too soon: IfElapsed %d, ExpireAfter %d\n",VIFELAPSED,VEXPIREAFTER);
- SendTransaction(conn,sendbuffer);
- return;
- }
-
- ExpandVarstring("$(cfrunCommand) --no-splay --inform",buffer,"");
-
- if (strlen(buffer)+strlen(args)+6 > bufsize)
- {
- sprintf(sendbuffer,"Command line too long with args: %s\n",buffer);
- SendTransaction(conn,sendbuffer);
- ReleaseCurrentLock();
- return;
- }
- else
- {
- if ((args != NULL) & (strlen(args) > 0))
- {
- strcat(buffer," ");
- strcat(buffer,args);
-
- sprintf(sendbuffer,"cfd: Executing %s\n",buffer);
- SendTransaction(conn,sendbuffer);
- }
- }
-
- sprintf(conn->output,"Executing command %s\n",buffer);
- CfLog(cfinform,conn->output,"");
-
- bzero(sendbuffer,bufsize);
-
- if ((pp = cfpopen(buffer,"r")) == NULL)
- {
- sprintf(conn->output,"Couldn't open pipe to command %s\n",buffer);
- CfLog(cferror,conn->output,"pipe");
-
- sprintf(sendbuffer,"Unable to run %s\n",buffer);
- SendTransaction(conn,sendbuffer);
- ReleaseCurrentLock();
- return;
- }
-
- while (!feof(pp))
- {
- if (ferror(pp)) /* abortable */
- {
- fflush(pp);
- break;
- }
-
- ReadLine(line,bufsize,pp);
-
- if (ferror(pp)) /* abortable */
- {
- fflush(pp);
- break;
- }
-
- print = false;
-
- for (sp = line; *sp != '\0'; sp++)
- {
- if (! isspace(*sp))
- {
- print = true;
- break;
- }
- }
-
- if (print)
- {
- sprintf(sendbuffer,"%s\n",line);
- SendTransaction(conn,sendbuffer);
- }
- }
-
- cfpclose(pp);
- ReleaseCurrentLock();
- }
-
-
- /**************************************************************/
-
- GetCommand (str)
-
- char *str;
-
- { int i;
- char op[bufsize];
-
- sscanf(str,"%4095s",op);
-
- for (i = 0; COMMANDS[i] != NULL; i++)
- {
- if (strcmp(op,COMMANDS[i])==0)
- {
- return i;
- }
- }
-
- return -1;
- }
-
- /*********************************************************************/
-
- VerifyConnection(conn,buf)
-
- /* Try reverse tcpwrap (if we have it), reverse DNS lookup
- and RFC931 username lookup to check the authenticity. */
-
- struct cfd_connection *conn;
- char buf[bufsize];
-
- { struct sockaddr_in raddr,laddr;
- char ipstring[maxvarsize], fqname[256], username[256];
- char name1[256], name2[256], name3[256], rusername[256];
- struct hostent *hp;
- int len, i, j, found;
-
- Debug("Connecting host identifies itself as %s\n",buf);
-
- bzero(ipstring,maxvarsize);
- bzero(fqname,256);
- bzero(username,256);
-
- sscanf(buf,"%255s %255s %255s %8s",ipstring,fqname,username,conn->signature);
- len = sizeof(struct sockaddr_in);
-
- if (getpeername(conn->sd_reply,(struct sockaddr *)&raddr,&len) == -1)
- {
- CfLog(cferror,"Couldn't get socket address\n","getpeername");
- return false;
- }
-
- strcpy(name1,ToLowerStr(fqname));
- strcpy(name2,ToLowerStr(inet_ntoa(raddr.sin_addr)));
- strcpy(name3,ToLowerStr(ipstring));
-
- if (strcmp(name2,name3) != 0)
- {
- Verbose("IP address mismatch between client's assertion and socket - untrustworthy connection\n");
- return false;
- }
- else
- {
- Verbose("Socket caller address appears honest\n");
- strncpy(conn->ipaddr,name3,sizeof(conn->ipaddr)-1);
- }
-
- sprintf(conn->output,"Socket originates from %s=%s with signature %8s\n",name2,name1,conn->signature);
- CfLog(cfverbose,conn->output,"");
-
- #if defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP)
-
- if (!hosts_ctl("cfd",name1,name2,username))
- {
- Verbose("TCPwrap(%s,%s,%s) rejects this packet\n",name1,name2,username);
- return false;
- }
-
- #endif
-
- /* Do our own checking ... */
-
- Debug("Attempting to look up hostname %s\n",name1);
-
- #ifdef HAVE_PTHREAD_H
- if (pthread_mutex_lock(&MUTEX_HOSTNAME) != 0)
- {
- CfLog(cferror,"pthread_mutex_lock failed","pthread_mutex_lock");
- return false;
- }
- #endif
-
- if ((hp = gethostbyname(name1)) == NULL)
- {
- Verbose("cfd: Couldn't look up name %s\n",fqname);
- Verbose(" Make sure that fully qualified names can be looked up at your site!\n");
- Verbose(" i.e. prep.ai.mit.edu, not just prep. If you use NIS or /etc/hosts\n");
- Verbose(" make sure that the full form is registered too as an alias!\n");
-
- #ifdef HAVE_PTHREAD_H
- if (pthread_mutex_unlock(&MUTEX_HOSTNAME) != 0)
- {
- CfLog(cferror,"pthread_mutex_unlock failed","unlock");
- }
- #endif
-
-
- return false;
- }
-
- #ifdef HAVE_PTHREAD_H
- if (pthread_mutex_unlock(&MUTEX_HOSTNAME) != 0)
- {
- CfLog(cferror,"pthread_mutex_unlock failed","unlock");
- exit(1);
- }
- #endif
-
-
- /* Now let's verify that the ip which gave us this hostname
- * is really an ip for this hostname; or is someone trying to
- * break in? (THIS IS THE CRUCIAL STEP)
- * Patch from Gunnar Gunnarsson, Ericsson */
-
- for (i = 0; hp->h_addr_list[i]; i++)
- {
- if (memcmp(hp->h_addr_list[i],(char *)&(raddr.sin_addr),sizeof(raddr.sin_addr)) == 0)
- {
- break; /* name is good, keep it */
- }
- }
-
- /* If we did not find it, your DNS is messed up or someone is trying
- * to pull a fast one on you. :(
- */
-
- /* Check even the aliases list. Work around for Solaris if dns goes over NIS */
-
- if (!hp->h_addr_list[i])
- {
- for (j=0;hp->h_aliases[j]!=0;j++)
- {
- if (strcmp(hp->h_aliases[j],name2) == 0)
- {
- break; /* name is good, keep it */
- }
- }
- }
-
-
- if (!hp->h_addr_list[i] && !hp->h_aliases[j])
- {
- sprintf(conn->output,"Reverse hostname lookup failed, host claiming to be %s was %s\n",buf,inet_ntoa(raddr.sin_addr));
- CfLog(cfinform,conn->output,"");
- return false;
- }
-
- Debug("Host ID is %s\n",name1);
- strncpy(conn->hostname,name1,maxvarsize);
-
- if (getsockname(conn->sd_reply,(struct sockaddr *)&laddr,&len) == -1)
- {
- CfLog(cferror,"Couldn't get socket address\n","getsockname");
- return false;
- }
-
- if (CHECK_RFC931)
- {
- if (DoRFC931(&(laddr.sin_addr),&(raddr.sin_addr),ntohs(laddr.sin_port),ntohs(raddr.sin_port),rusername))
- {
- Debug("Remote host got %s as username, local=%s\n",rusername,username);
- if (strcmp(ToLowerStr(username),ToLowerStr(rusername)) == 0)
- {
- Debug("User ID confirmed as %s\n",username);
- strncpy(conn->username,username,maxvarsize);
- return true;
- }
- else
- {
- CfLog(cferror,"Username RFC931 authentication failed","");
- sprintf(conn->output,"Source spoofed user %s but was actually %s\n",username,rusername);
- CfLog(cferror,conn->output,"");
- return false;
- }
- }
- else
- {
- CfLog(cferror,"RFC931 lookup failed on source host\n","");
- return false;
- }
- }
-
- Debug("User ID seems to be %s\n",username);
- strncpy(conn->username,username,maxvarsize);
- return true;
- }
-
- /**************************************************************/
-
- RefuseAccess(conn,sendbuffer)
-
- struct cfd_connection *conn;
- char *sendbuffer;
-
- {
- sprintf(sendbuffer,"%s",CFFAILEDSTR);
- CfLog(cfinform,"Host authentication failed or access denied\n","");
-
- SendTransaction(conn,sendbuffer);
- }
-
- /**************************************************************/
-
- AccessControl(filename,conn,secure)
-
- char *filename;
- struct cfd_connection *conn;
- int secure;
-
- { struct Auth *ap;
- int access = false;
- char realname[bufsize];
- struct stat statbuf;
-
- Debug("AccessControl(%s)\n",filename);
- bzero(realname,bufsize);
-
- #ifdef HAVE_REALPATH
- if (realpath(filename,realname) == NULL)
- {
- sprintf(conn->output,"Couldn't resolve filename %s from host %s\n",filename,conn->hostname);
- CfLog(cferror,conn->output,"");
- return false;
- }
- #else
- CompressPath(realname,filename); /* in links.c */
- #endif
-
- Debug("AccessControl(%s,%s) secure=%d\n",realname,conn->hostname,secure);
-
- if (VADMIT == NULL)
- {
- Verbose("cfd: access list is empty, no files are visible\n");
- return false;
- }
-
- conn->maproot = false;
-
- for (ap = VADMIT; ap != NULL; ap=ap->next)
- {
- if (strncmp(ap->path,realname,strlen(ap->path)) == 0)
- {
- if (stat(ap->path,&statbuf) == -1)
- {
- Verbose("Warning cannot stat file object %s in admit/grant\n",ap->path);
- continue;
- }
-
- if (!secure && (ap->secure == true))
- {
- Debug("File requires secure connection...will not serve\n");
- access = false;
- }
- else
- {
- if (access = IsWildItemIn(ap->accesslist,conn->hostname))
- {
- }
- else
- {
- access = IsWildItemIn(ap->accesslist,conn->ipaddr);
- }
-
- if (IsWildItemIn(ap->maproot,conn->hostname))
- {
- conn->maproot = true;
- }
- else if (IsWildItemIn(ap->maproot,conn->ipaddr))
- {
- conn->maproot = true;
- }
- }
- break;
- }
- }
-
- for (ap = VDENY; ap != NULL; ap=ap->next)
- {
- if (strncmp(ap->path,realname,strlen(ap->path)) == 0)
- {
- if (IsWildItemIn(ap->accesslist,conn->hostname))
- {
- access = false;
- break;
- }
- }
- }
-
- if (access)
- {
- sprintf(conn->output,"Host %s granted access to %s\n",conn->hostname,realname);
- CfLog(cfverbose,conn->output,"");
- }
- else
- {
- sprintf(conn->output,"Host %s denied access to %s\n",conn->hostname,realname);
- CfLog(cfinform,conn->output,"");
- }
-
- return access;
- }
-
- /**************************************************************/
-
- StatFile(conn,sendbuffer,filename)
-
- struct cfd_connection *conn;
- char *sendbuffer, *filename;
-
- /* Because we do not know the size or structure of remote datatypes,*/
- /* the simplest way to transfer the data is to convert them into */
- /* plain text and interpret them on the other side. */
-
- { struct cfstat cfst;
- struct stat statbuf;
- char linkbuf[bufsize];
-
- Debug("StatFile(%s)\n",filename);
-
- bzero(&cfst,sizeof(struct cfstat));
-
- if (strlen(filename) > maxlinksize)
- {
- sprintf(sendbuffer,"BAD: Filename suspiciously long\n");
- CfLog(cferror,sendbuffer,"");
- SendTransaction(conn,sendbuffer);
- return -1;
- }
-
- if (lstat(filename,&statbuf) == -1)
- {
- sprintf(sendbuffer,"BAD: unable to stat file %s",filename);
- CfLog(cfverbose,sendbuffer,"lstat");
- SendTransaction(conn,sendbuffer);
- return -1;
- }
-
- cfst.cf_readlink = NULL;
- cfst.cf_lmode = 0;
- cfst.cf_nlink = cfnosize;
-
- bzero(linkbuf,bufsize);
-
- if (S_ISLNK(statbuf.st_mode))
- {
- cfst.cf_type = cf_link; /* pointless - overwritten */
- cfst.cf_lmode = statbuf.st_mode & 07777;
- cfst.cf_nlink = statbuf.st_nlink;
-
- if (readlink(filename,linkbuf,bufsize) == -1)
- {
- sprintf(sendbuffer,"BAD: unable to read link\n");
- CfLog(cferror,sendbuffer,"readlink");
- SendTransaction(conn,sendbuffer);
- return -1;
- }
-
- Debug("readlink: %s\n",linkbuf);
-
- cfst.cf_readlink = linkbuf;
- }
-
- if (stat(filename,&statbuf) == -1)
- {
- sprintf(sendbuffer,"BAD: unable to stat file %s\n",filename);
- CfLog(cfverbose,conn->output,"stat");
- SendTransaction(conn,sendbuffer);
- return -1;
- }
-
- if (S_ISDIR(statbuf.st_mode))
- {
- cfst.cf_type = cf_dir;
- }
-
- if (S_ISREG(statbuf.st_mode))
- {
- cfst.cf_type = cf_reg;
- }
-
- if (S_ISSOCK(statbuf.st_mode))
- {
- cfst.cf_type = cf_sock;
- }
-
- if (S_ISCHR(statbuf.st_mode))
- {
- cfst.cf_type = cf_char;
- }
-
- if (S_ISBLK(statbuf.st_mode))
- {
- cfst.cf_type = cf_block;
- }
-
- if (S_ISFIFO(statbuf.st_mode))
- {
- cfst.cf_type = cf_fifo;
- }
-
- cfst.cf_mode = statbuf.st_mode & 07777; /* Make sure everything is 32 bit */
- cfst.cf_uid = statbuf.st_uid & 0xFFFFFFFF;
- cfst.cf_gid = statbuf.st_gid & 0xFFFFFFFF;
- cfst.cf_size = statbuf.st_size & 0xFFFFFFFF;
- cfst.cf_atime = statbuf.st_atime & 0xFFFFFFFF;
- cfst.cf_mtime = statbuf.st_mtime & 0xFFFFFFFF;
- cfst.cf_ctime = statbuf.st_ctime & 0xFFFFFFFF;
- cfst.cf_ino = statbuf.st_ino;
- cfst.cf_readlink = linkbuf;
-
- if (cfst.cf_nlink == cfnosize)
- {
- cfst.cf_nlink = statbuf.st_nlink;
- }
-
- #ifndef IRIX
- if (statbuf.st_size > statbuf.st_blocks * DEV_BSIZE)
- #else
- # ifdef HAVE_ST_BLOCKS
- if (statbuf.st_size > statbuf.st_blocks * DEV_BSIZE)
- # else
- if (statbuf.st_size > ST_NBLOCKS(statbuf) * DEV_BSIZE)
- # endif
- #endif
- {
- cfst.cf_makeholes = 1; /* must have a hole to get checksum right */
- }
- else
- {
- cfst.cf_makeholes = 0;
- }
-
-
- bzero(sendbuffer,bufsize);
-
- /* send as plain text */
-
- Debug("OK: type=%d\n mode=%o\n lmode=%o\n uid=%d\n gid=%d\n size=%ld\n atime=%d\n mtime=%d\n",
- cfst.cf_type,cfst.cf_mode,cfst.cf_lmode,cfst.cf_uid,cfst.cf_gid,(long)cfst.cf_size,
- cfst.cf_atime,cfst.cf_mtime);
-
-
- sprintf(sendbuffer,"OK: %d %d %d %d %d %ld %d %d %d %d %d %d",
- cfst.cf_type,cfst.cf_mode,cfst.cf_lmode,cfst.cf_uid,cfst.cf_gid,(long)cfst.cf_size,
- cfst.cf_atime,cfst.cf_mtime,cfst.cf_ctime,cfst.cf_makeholes,cfst.cf_ino,cfst.cf_nlink);
-
- SendTransaction(conn,sendbuffer);
- bzero(sendbuffer,bufsize);
-
- if (cfst.cf_readlink != NULL)
- {
- strcpy(sendbuffer,"OK:");
- strcat(sendbuffer,cfst.cf_readlink);
- }
- else
- {
- sprintf(sendbuffer,"OK:");
- }
-
- SendTransaction(conn,sendbuffer);
- return 0;
- }
-
-
- /***************************************************************/
-
- CfGetFile(args)
-
- struct cfd_get_arg *args;
-
- { int sd,fd, n_read,total=0,size_at_start,i=0;
- char sendbuffer[bufsize],out[bufsize],*filename;
- struct stat statbuf;
- struct passwd *pw;
- uid_t uid;
-
- #ifdef HAVE_UTIME_H
- struct utimbuf timebuf;
- #endif
-
- sd = (args->connect)->sd_reply;
- filename = args->replyfile;
-
- if ((pw=getpwnam((args->connect)->username)) == NULL)
- {
- uid = -2;
- }
- else
- {
- uid = pw->pw_uid;
- }
-
- stat(filename,&statbuf);
- Debug("CfGetFile(%s on sd=%d), size=%d\n",filename,sd,statbuf.st_size);
-
- size_at_start = statbuf.st_size;
-
- /* Now check to see if we have remote permission */
-
- if (uid != 0 && !args->connect->maproot) /* should remote root be local root */
- {
- if (statbuf.st_uid == uid)
- {
- Debug("Caller %s is the owner of the file\n",(args->connect)->username);
- }
- else
- {
- /* We are not the owner of the file and we don't care about groups */
- if (statbuf.st_mode & S_IROTH)
- {
- Debug("Caller %s not owner of the file but permission granted\n",(args->connect)->username);
- }
- else
- {
- Debug("Caller %s is not the owner of the file\n",(args->connect)->username);
- RefuseAccess(args->connect,sendbuffer);
- return;
- }
- }
- }
-
- if (args->buf_size < 512)
- {
- sprintf(args->connect->output,"blocksize for %s was only %d\n",filename,args->buf_size);
- CfLog(cferror,args->connect->output,"");
- }
-
- if ((fd = open(filename,O_RDONLY)) == -1)
- {
- sprintf(sendbuffer,"%s",CFFAILEDSTR);
- CfLog(cferror,sendbuffer,"open");
- SendTransaction(args->connect,sendbuffer);
- sprintf(sendbuffer,"Open error of file [%s]\n",filename);
- CfLog(cferror,sendbuffer,"open");
- }
- else
- {
- while(true)
- {
- bzero(sendbuffer,bufsize);
-
- if ((n_read = read(fd,sendbuffer,args->buf_size)) == -1)
- {
- close(fd);
- CfLog(cferror,"read failed in GetFile","read");
- break;
- }
-
- if (n_read == 0)
- {
- close(fd);
- break;
- }
- else
- { int save = statbuf.st_size;
-
- /* This can happen with log files /databases etc */
-
- stat(filename,&statbuf);
-
- if (statbuf.st_size != save)
- {
- sprintf(sendbuffer,"BAD:File %s changed while copying",filename);
- if (send(sd,sendbuffer,args->buf_size,0) == -1)
- {
- CfLog(cferror,"Send failed in GetFile","send");
- }
-
- Debug("Aborting transfer after %d: file is changing rapidly at source.\n",total);
- close(fd);
- break;
- }
- }
-
- total += n_read;
-
- if (args->secure)
- {
- bzero(out,bufsize);
- cfencrypt(sendbuffer,out,CFDES1,args->key,CFDES3,args->buf_size); /* use session key */
-
- /* Need to pad out to buf_size rather than stop at n_read
- because encryption requires an 8-byte divisible block */
-
- if (send(sd,out,args->buf_size,0) == -1)
- {
- close(fd);
- CfLog(cferror,"Send failed in GetFile","send");
- break;
- }
- }
- else
- {
- if (send(sd,sendbuffer,args->buf_size,0) == -1)
- {
- close(fd);
- CfLog(cferror,"Send failed in GetFile","send");
- break;
- }
- }
- }
- }
-
- Debug("Done with GetFile()\n");
- }
-
- /**************************************************************/
-
- CompareLocalChecksum(conn,sendbuffer,recvbuffer)
-
- struct cfd_connection *conn;
- char *sendbuffer, *recvbuffer;
-
- { unsigned char digest[17], num[5],filename[bufsize];
- char *sp;
- int i,len;
-
- sscanf(recvbuffer,"MD5 %[^\n]",filename);
-
- sp = recvbuffer+6+strlen(filename); /* Finr md5 */
-
- Debug("Got filename %s, sp=%s\n",filename,sp);
-
- for (i = 0; i < 16; i++)
- {
- bzero(num,5);
- sscanf(sp,"%4s",num);
- digest[i] = (char) atoi(num);
- sp += strlen((char *)num) + 1;
- }
-
- Debug("CompareLocalChecksums(%s)\n",cfMDPrint(digest));
- bzero(sendbuffer,bufsize);
-
- if (ChecksumChanged(filename,digest,cfverbose,true))
- {
- sprintf(sendbuffer,"%s",CFD_TRUE);
- Debug("Checksums didn't match\n");
- SendTransaction(conn,sendbuffer);
- return;
- }
- else
- {
- sprintf(sendbuffer,"%s",CFD_FALSE);
- Debug("Checksums matched ok\n");
- SendTransaction(conn,sendbuffer);
- }
- }
-
- /**************************************************************/
-
- CfOpenDirectory(conn,sendbuffer,dirname)
-
- struct cfd_connection *conn;
- char *sendbuffer, *dirname;
-
- { DIR *dirh;
- struct dirent *dirp;
- int offset;
-
- Debug("CfOpenDirectory(%s)\n",dirname);
-
- if (*dirname != '/')
- {
- sprintf(sendbuffer,"BAD: request to access a non-absolute filename\n");
- SendTransaction(conn,sendbuffer);
- return -1;
- }
-
- if ((dirh = opendir(dirname)) == NULL)
- {
- Debug("cfengine, couldn't open dir %s\n",dirname);
- sprintf(sendbuffer,"BAD: cfengine, couldn't open dir %s\n",dirname);
- SendTransaction(conn,sendbuffer);
- return -1;
- }
-
- /* Pack names for transmission */
-
- bzero(sendbuffer,bufsize);
-
- offset = 0;
-
- for (dirp = readdir(dirh); dirp != NULL; dirp = readdir(dirh))
- {
- if (strlen(dirp->d_name)+1+offset >= bufsize - buffer_margin)
- {
- SendTransaction(conn,sendbuffer);
- offset = 0;
- bzero(sendbuffer,bufsize);
- }
-
- strncpy(sendbuffer+offset,dirp->d_name,maxlinksize);
- offset += strlen(dirp->d_name) + 1; /* + zero byte separator */
- }
-
- strcpy(sendbuffer+offset,CFD_TERMINATOR);
-
- SendTransaction(conn,sendbuffer);
- closedir(dirh);
- return 0;
- }
-
- /***************************************************************/
-
- Terminate(sd)
-
- int sd;
-
- { char buffer[bufsize];
-
- bzero(buffer,bufsize);
-
- strcpy(buffer,CFD_TERMINATOR);
-
- if (send(sd,buffer,strlen(buffer)+1,0) == -1)
- {
- CfLog(cferror,"","send");
- Verbose("Unable to reply with terminator...\n");
- }
- }
-
- /***************************************************************/
-
- DeleteAuthList(ap)
-
- struct Auth *ap;
-
- {
- if (ap != NULL)
- {
- DeleteAuthList(ap->next);
- ap->next = NULL;
-
- DeleteItemList(ap->accesslist);
-
- free((char *)ap);
- }
- }
-
- /***************************************************************/
- /* Level 5 */
- /***************************************************************/
-
- DoRFC931(laddr,raddr,local,remote,username)
-
- /* Not many OSes have this authentication service, alas */
-
- struct in_addr *laddr, *raddr;
- unsigned short local,remote;
- char username[256];
-
- { struct sockaddr_in saddr;
- char sendbuffer[maxvarsize],recvbuffer[bufsize], *sp;
- int n_read, sd, yes=1;
-
- if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
- {
- return false;
- }
-
- /* Identify ourselves with this address */
-
- bind(sd,(struct sockaddr *)laddr,sizeof(laddr));
-
- setsockopt(sd,SOL_SOCKET,SO_REUSEADDR,(char *)&yes,sizeof(int));
-
- saddr.sin_family = AF_INET;
- saddr.sin_port = htons(RFC931_PORT);
- saddr.sin_addr.s_addr = raddr->s_addr;
-
- if (connect(sd,(struct sockaddr *)&saddr,sizeof(saddr)) == -1)
- {
- CfLog(cferror,"Couldn't connect to verify RFC931\n","connect");
- close(sd);
- return false;
- }
-
- /* The RFC document is misleading...careful with order */
-
- sprintf(sendbuffer,"%u , %u\r\n",(unsigned int)remote,(unsigned int)local);
-
- if (send(sd,sendbuffer,strlen(sendbuffer),0) == -1)
- {
- CfLog(cferror,"Couldn't send to verify RFC931\n","send");
- close(sd);
- return false;
- }
-
- if ((n_read = recv(sd, recvbuffer, bufsize,0)) == -1)
- {
- CfLog(cferror,"Couldn't recv to verify RFC931\n","recv");
- close(sd);
- return false;
- }
-
- close(sd);
-
- Debug("AUTH server returned %s\n",recvbuffer);
-
- if (strstr(recvbuffer,"ERROR"))
- {
- Verbose("RFC931 checking reveals no such user connection at source!\n");
- return false;
- }
-
- /* e.g. AUTH server returned 8530 , 5308 : USERID : UNIX : mark */
-
- for (sp = recvbuffer; *sp != ':'; sp++)
- {
- }
-
- sp++;
-
- while (*sp != ':')
- {
- sp++;
- }
-
- sp++;
-
- sendbuffer[0] = '\0';
- username[0] = '\0';
- Debug("Checking %s\n",sp);
- sscanf(sp,"%255s %*[:] %255s",sendbuffer,username);
-
- Debug("Operating system type of remote host was %s and user was %s\n",sendbuffer,username);
- return true;
- }
-
-
- /***************************************************************/
-
- ReplyNothing(conn)
-
- struct cfd_connection *conn;
-
- { char buffer[bufsize];
-
- sprintf(buffer,"Hello %s, nothing to do here...\n",conn->hostname,VFQNAME);
-
- if (send(conn->sd_reply,buffer,bufsize,0) == -1)
- {
- CfLog(cferror,"","send");
- }
- }
-
- /***************************************************************/
- /* Toolkit/Class: conn */
- /***************************************************************/
-
- struct cfd_connection *NewConn(sd) /* construct */
-
- int sd;
-
- { struct cfd_connection *conn;
-
- conn = (struct cfd_connection *) malloc(sizeof(struct cfd_connection));
-
- conn->sd_reply = sd;
- conn->id_verified = false;
- conn->hostname[0] = '\0';
- Debug("***New socket %d\n",sd);
-
- return conn;
- }
-
- /***************************************************************/
-
- DeleteConn(conn) /* destruct */
-
- struct cfd_connection *conn;
-
- {
- Debug("***Closing socket %d\n",conn->sd_reply);
- close(conn->sd_reply);
- free ((char *)conn);
- }
-
- /*************************************************************************/
-
- SendTransaction(conn,buffer)
-
- struct cfd_connection *conn;
- char *buffer;
-
- {
- /* Send a fixed size transmission
- so that it will be read at the other end */
- Debug("SendTransaction()\n");
- if (send(conn->sd_reply,buffer,bufsize,0) == -1)
- {
- CfLog(cferror,"Couldn't send","send");
- return -1;
- }
- }
-
-
- /* EOF */
-
-
-
-